<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>表格拖动-列</title>
	<style>

		.table {
			border: 1px solid #ccc;
			border-collapse: collapse;
		}
		.table th,
		.table td {
			border: 1px solid #ccc;
		}
		.table th,
		.table td {
			padding: 10px;
			text-align: center;
			box-sizing: border-box;
		}
		.draggable {
			cursor: move;
			user-select: none;
		}
		.list {
			border-left: 1px solid #ccc;
			border-top: 1px solid #ccc;
			display: flex;
		}
		.list__table {
			border-collapse: collapse;
			border: none;
		}
		.list__table th,
		.list__table td {
			border: 1px solid #ccc;
			border-left: none;
			border-top: none;
			box-sizing: border-box;
			padding: 10px;
			text-align: center;
			/* color: red; */
		}
		.placeholder {
			background-color: #edf2f7;
			border: 2px dashed #cbd5e0;
			box-sizing: border-box;
		}
		.dragging {
			background: #fff;
			border-left: 1px solid #ccc;
			border-top: 1px solid #ccc;
			z-index: 999;
		}
	</style>
</head>

<body>
	<table id="table" class="table">
		<thead>
			<tr>
				<th>序号</th>
				<th>日期</th>
				<th>姓名</th>
				<th>省份</th>
				<th>城市</th>
				<th>地址</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>1</td>
				<td>2024-04-01</td>
				<td>小小红</td>
				<td>广东</td>
				<td>广州市</td>
				<td>广东省广州市xxxxxx</td>
			</tr>
			<tr>
				<td>2</td>
				<td>2024-04-02</td>
				<td>小小绿</td>
				<td>广东</td>
				<td>深圳市</td>
				<td>广东省深圳市xxxxxx</td>
			</tr>
			<tr>
				<td>3</td>
				<td>2024-04-03</td>
				<td>小小黄</td>
				<td>广东</td>
				<td>中山市</td>
				<td>广东省中山市xxxxx</td>
			</tr>
			<tr>
				<td>4</td>
				<td>2024-04-04</td>
				<td>小小白</td>
				<td>广东</td>
				<td>佛山市</td>
				<td>广东省佛山市xxxx</td>
			</tr>
			<tr>
				<td>5</td>
				<td>2024-04-05</td>
				<td>小小黑</td>
				<td>广东</td>
				<td>汕头市</td>
				<td>广东省汕头市xxxxxx</td>
			</tr>
		</tbody>
	</table>

	<script>
		document.addEventListener('DOMContentLoaded', () => {
			const table = document.getElementById('table');
			table.querySelectorAll('th').forEach(headerCell => {
				headerCell.classList.add('draggable');
				headerCell.addEventListener('mousedown', mouseDownHandler);
			});
			let draggingColumnIndex;
			let x = 0;
			let y = 0;
			let isDraggingStarted = false;
			let list;
			let draggingElement;
			let placeholder;
			function mouseDownHandler(e) {
				draggingColumnIndex = [].slice.call(table.querySelectorAll('th')).indexOf(e.target);
				x = e.clientX - e.target.offsetLeft;
				y = e.clientY - e.target.offsetTop;
				document.addEventListener('mousemove', mouseMoveHandler);
				document.addEventListener('mouseup', mouseUpHandler);
			};
			function mouseMoveHandler(e) {
				if (!isDraggingStarted) {
					isDraggingStarted = true;
					createList();
					draggingElement = [].slice.call(list.children)[draggingColumnIndex];
					draggingElement.classList.add('dragging');
					placeholder = document.createElement('div');
					placeholder.classList.add('placeholder');
					draggingElement.parentNode.insertBefore(placeholder, draggingElement.nextSibling);
					placeholder.style.width = draggingElement.offsetWidth + 'px';
				}
				draggingElement.style.position = 'absolute';
				draggingElement.style.top = (draggingElement.offsetTop + e.clientY - y) + 'px';
				draggingElement.style.left = (draggingElement.offsetLeft + e.clientX - x) + 'px';
				x = e.clientX;
				y = e.clientY;
				const prevEle = draggingElement.previousElementSibling;
				const nextEle = placeholder.nextElementSibling;
				if (prevEle && isOnLeft(draggingElement, prevEle)) {
					swap(placeholder, draggingElement);
					swap(placeholder, prevEle);
					return;
				}
				if (nextEle && isOnLeft(nextEle, draggingElement)) {
					swap(nextEle, placeholder);
					swap(nextEle, draggingElement);
				}
			};

			function createList() {
				const rect = table.getBoundingClientRect();

				list = document.createElement('div');
				list.classList.add('list');
				list.style.position = 'absolute';
				list.style.left = rect.left + 'px';
				list.style.top = rect.top + 'px';
				table.parentNode.insertBefore(list, table);
				table.style.visibility = 'hidden';
				const originalCells = [].slice.call(table.querySelectorAll('tbody td'));
				const originalHeaderCells = [].slice.call(table.querySelectorAll('th'));
				const numColumns = originalHeaderCells.length;
				originalHeaderCells.forEach((headerCell, headerIndex) => {
					const { width } = window.getComputedStyle(headerCell);
					const item = document.createElement('div');
					item.classList.add('draggable');
					const newTable = document.createElement('table');
					newTable.setAttribute('class', 'list__table');
					newTable.style.width = width;
					const th = headerCell.cloneNode(true);
					let newRow = document.createElement('tr');
					newRow.appendChild(th);
					newTable.appendChild(newRow);
					const cells = originalCells.filter((c, idx) => {
						return (idx - headerIndex) % numColumns === 0;
					});
					cells.forEach(cell => {
						const newCell = cell.cloneNode(true);
						newCell.style.width = width + 'px';
						newRow = document.createElement('tr');
						newRow.appendChild(newCell);
						newTable.appendChild(newRow);
					});

					item.appendChild(newTable);
					list.appendChild(item);
				});
			};
			function swap(nodeA, nodeB) {
				const parentA = nodeA.parentNode;
				const siblingA = nodeA.nextSibling === nodeB ? nodeA : nodeA.nextSibling;
				nodeB.parentNode.insertBefore(nodeA, nodeB);
				parentA.insertBefore(nodeB, siblingA);
			};
			function isOnLeft(nodeA, nodeB) {
				const rectA = nodeA.getBoundingClientRect();
				const rectB = nodeB.getBoundingClientRect();
				const centerPointA = rectA.left + rectA.width / 2;
				const centerPointB = rectB.left + rectB.width / 2;
				return centerPointA < centerPointB;
			};
			function mouseUpHandler() {
				placeholder && placeholder.parentNode.removeChild(placeholder);
				draggingElement.classList.remove('dragging');
				draggingElement.style.removeProperty('top');
				draggingElement.style.removeProperty('left');
				draggingElement.style.removeProperty('position');
				const endColumnIndex = [].slice.call(list.children).indexOf(draggingElement);
				isDraggingStarted = false;
				list.parentNode.removeChild(list);
				table.querySelectorAll('tr').forEach(row => {
					const cells = [].slice.call(row.querySelectorAll('th, td'));
					console.log(cells)
					if (draggingColumnIndex > endColumnIndex) {
						console.log(cells[endColumnIndex].parentNode)
						console.log(cells[draggingColumnIndex], cells[endColumnIndex])
						cells[endColumnIndex].parentNode.insertBefore(
							cells[draggingColumnIndex],
							cells[endColumnIndex]
						)
					}else {
						cells[endColumnIndex].parentNode.insertBefore(
							cells[draggingColumnIndex],
							cells[endColumnIndex].nextSibling
						);
					}
				});
				table.style.removeProperty('visibility');
				document.removeEventListener('mousemove', mouseMoveHandler);
				document.removeEventListener('mouseup', mouseUpHandler);
			};
		});
	</script>
</body>

</html>
